/**
 * Notes: 简化故障处理服务 - 针对开关面板设备的故障处理
 * Date: 2025-01-27
 */

const BaseService = require('./base_service.js');
const DeviceModel = require('../model/device_model.js');
const timeUtil = require('../../framework/utils/time_util.js');
const util = require('../../framework/utils/util.js');
const AppError = require('../../framework/core/app_error.js');
const appCode = require('../../framework/core/app_code.js');
const config = require('../../config/config.js');

class SimpleFaultHandler extends BaseService {

    constructor() {
        super();
        this.faultHistory = new Map(); // 故障历史记录
        this.recoveryAttempts = new Map(); // 恢复尝试记录
        this.maxRecoveryAttempts = 3; // 最大恢复尝试次数
        this.recoveryInterval = 30000; // 恢复尝试间隔 30秒
        this.faultCooldown = 60000; // 故障冷却时间 60秒
    }

    /**
     * 处理设备故障
     * @param {Object} deviceStatus 设备状态信息
     * @param {string} faultType 故障类型
     */
    async handleDeviceFault(deviceStatus, faultType) {
        const deviceId = deviceStatus.deviceId;
        const currentTime = Date.now();
        
        console.log(`处理设备故障: ${deviceId}, 故障类型: ${faultType}`);

        // 检查是否在冷却期内
        if (this.isInCooldown(deviceId, currentTime)) {
            console.log(`设备 ${deviceId} 在故障冷却期内，跳过处理`);
            return;
        }

        // 记录故障信息
        const faultRecord = {
            deviceId: deviceId,
            faultType: faultType,
            timestamp: currentTime,
            deviceStatus: deviceStatus,
            handled: false,
            recovered: false
        };

        this.recordFault(deviceId, faultRecord);

        // 根据故障类型进行处理
        switch (faultType) {
            case 'offline':
                await this.handleOfflineFault(deviceStatus, faultRecord);
                break;
            case 'switch_abnormal':
                await this.handleSwitchAbnormalFault(deviceStatus, faultRecord);
                break;
            case 'no_response':
                await this.handleNoResponseFault(deviceStatus, faultRecord);
                break;
            default:
                await this.handleUnknownFault(deviceStatus, faultRecord);
                break;
        }

        faultRecord.handled = true;
    }

    /**
     * 处理设备离线故障
     */
    async handleOfflineFault(deviceStatus, faultRecord) {
        const deviceId = deviceStatus.deviceId;
        
        console.log(`处理设备离线故障: ${deviceId}`);

        try {
            // 1. 更新数据库中的设备状态
            await this.updateDeviceOfflineStatus(deviceId);

            // 2. 检查是否有正在进行的订单
            const activeOrder = await this.checkActiveOrder(deviceId);
            if (activeOrder) {
                // 3. 处理活跃订单 - 暂停或退款
                await this.handleActiveOrderForOfflineDevice(activeOrder, deviceId);
            }

            // 4. 发送离线告警
            await this.sendOfflineAlert(deviceId, deviceStatus);

            // 5. 尝试恢复连接
            await this.scheduleRecoveryAttempt(deviceId, 'offline');

            faultRecord.recovered = false; // 离线故障需要人工干预
            
        } catch (error) {
            console.error(`处理设备 ${deviceId} 离线故障失败:`, error);
            faultRecord.error = error.message;
        }
    }

    /**
     * 处理开关状态异常故障
     */
    async handleSwitchAbnormalFault(deviceStatus, faultRecord) {
        const deviceId = deviceStatus.deviceId;
        
        console.log(`处理开关状态异常故障: ${deviceId}, 状态: ${deviceStatus.switchStatus}`);

        try {
            // 1. 尝试重新获取设备状态
            const deviceService = require('./device_service.js');
            const realTimeStatus = await deviceService.getDeviceRealTimeStatus(deviceId);
            
            if (realTimeStatus && realTimeStatus.status !== undefined) {
                // 2. 状态已恢复正常
                console.log(`设备 ${deviceId} 状态已恢复正常`);
                faultRecord.recovered = true;
                return;
            }

            // 3. 尝试重置设备状态
            await this.resetDeviceStatus(deviceId);

            // 4. 发送状态异常告警
            await this.sendStatusAbnormalAlert(deviceId, deviceStatus);

            faultRecord.recovered = false;
            
        } catch (error) {
            console.error(`处理设备 ${deviceId} 开关状态异常失败:`, error);
            faultRecord.error = error.message;
        }
    }

    /**
     * 处理设备无响应故障
     */
    async handleNoResponseFault(deviceStatus, faultRecord) {
        const deviceId = deviceStatus.deviceId;
        
        console.log(`处理设备无响应故障: ${deviceId}`);

        try {
            // 1. 尝试发送ping指令
            const pingResult = await this.pingDevice(deviceId);
            
            if (pingResult.success) {
                console.log(`设备 ${deviceId} ping成功，故障已恢复`);
                faultRecord.recovered = true;
                return;
            }

            // 2. 尝试重启设备连接
            await this.restartDeviceConnection(deviceId);

            // 3. 发送无响应告警
            await this.sendNoResponseAlert(deviceId, deviceStatus);

            // 4. 安排恢复尝试
            await this.scheduleRecoveryAttempt(deviceId, 'no_response');

            faultRecord.recovered = false;
            
        } catch (error) {
            console.error(`处理设备 ${deviceId} 无响应故障失败:`, error);
            faultRecord.error = error.message;
        }
    }

    /**
     * 处理未知故障
     */
    async handleUnknownFault(deviceStatus, faultRecord) {
        const deviceId = deviceStatus.deviceId;
        
        console.log(`处理未知故障: ${deviceId}`);

        try {
            // 1. 记录详细的故障信息
            await this.logUnknownFault(deviceId, deviceStatus);

            // 2. 发送未知故障告警
            await this.sendUnknownFaultAlert(deviceId, deviceStatus);

            // 3. 尝试基本的恢复操作
            await this.performBasicRecovery(deviceId);

            faultRecord.recovered = false;
            
        } catch (error) {
            console.error(`处理设备 ${deviceId} 未知故障失败:`, error);
            faultRecord.error = error.message;
        }
    }

    /**
     * 更新设备离线状态
     */
    async updateDeviceOfflineStatus(deviceId, isOffline) {
        try {
            if (config.TEST_MODE && !config.TEST_CONFIG.ENABLE_REAL_DEVICE_STATUS) {
                console.log('TEST_MODE: 跳过设备离线状态数据库更新');
                return {
                    success: true,
                    message: 'TEST_MODE: 跳过设备离线状态数据库更新'
                };
            }

            await DeviceModel.edit(deviceId, {
                isOnline: false,
                lastOfflineTime: timeUtil.time()
            });

            console.log(`设备 ${deviceId} 离线状态已更新到数据库`);
        } catch (error) {
            console.error(`更新设备 ${deviceId} 离线状态失败:`, error);
            throw error;
        }
    }

    /**
     * 检查设备是否有活跃订单
     */
    async checkActiveOrder(deviceId) {
        try {
            const deviceStatusManager = require('./device_status_manager.js');
            const status = await deviceStatusManager.getDeviceRealTimeStatus(deviceId);
            
            if (status && status.orderId && status.status === DeviceModel.STATUS.IN_USE) {
                return {
                    orderId: status.orderId,
                    startTime: status.startTime,
                    endTime: status.endTime,
                    remainingTime: status.remainingTime
                };
            }

            return null;
        } catch (error) {
            console.error(`检查设备 ${deviceId} 活跃订单失败:`, error);
            return null;
        }
    }

    /**
     * 处理离线设备的活跃订单
     */
    async handleActiveOrderForOfflineDevice(activeOrder, deviceId) {
        try {
            console.log(`处理离线设备 ${deviceId} 的活跃订单:`, activeOrder);

            // 这里可以根据业务需求决定处理策略：
            // 1. 暂停订单，等待设备恢复
            // 2. 取消订单并退款
            // 3. 转移到其他可用设备

            // 当前实现：暂停订单
            const deviceStatusManager = require('./device_status_manager.js');
            await deviceStatusManager.pauseDeviceUsage(deviceId, {
                reason: 'device_offline',
                timestamp: timeUtil.time()
            });

            console.log(`设备 ${deviceId} 的订单已暂停`);

        } catch (error) {
            console.error(`处理离线设备 ${deviceId} 活跃订单失败:`, error);
        }
    }

    /**
     * 重置设备状态
     */
    async resetDeviceStatus(deviceId) {
        try {
            const deviceService = require('./device_service.js');
            
            // 尝试发送关闭指令重置设备
            await deviceService.controlDevice(deviceId, 'off');
            
            console.log(`设备 ${deviceId} 状态重置完成`);
        } catch (error) {
            console.error(`重置设备 ${deviceId} 状态失败:`, error);
            throw error;
        }
    }

    /**
     * Ping设备检查连通性
     */
    async pingDevice(deviceId) {
        try {
            // 这里可以实现具体的ping逻辑
            // 例如发送心跳包或状态查询指令
            
            // 暂时返回模拟结果
            console.log(`Ping设备 ${deviceId}`);
            
            return {
                success: false, // 默认失败，需要实际实现
                message: 'Ping功能待实现'
            };
        } catch (error) {
            console.error(`Ping设备 ${deviceId} 失败:`, error);
            return {
                success: false,
                message: error.message
            };
        }
    }

    /**
     * 重启设备连接
     */
    async restartDeviceConnection(deviceId) {
        try {
            console.log(`重启设备 ${deviceId} 连接`);
            
            // 这里可以实现重启连接的逻辑
            // 例如重新初始化MQTT连接等
            
            console.log(`设备 ${deviceId} 连接重启完成`);
        } catch (error) {
            console.error(`重启设备 ${deviceId} 连接失败:`, error);
            throw error;
        }
    }

    /**
     * 执行基本恢复操作
     */
    async performBasicRecovery(deviceId) {
        try {
            console.log(`执行设备 ${deviceId} 基本恢复操作`);
            
            // 1. 尝试重置设备状态
            await this.resetDeviceStatus(deviceId);
            
            // 2. 等待一段时间
            await new Promise(resolve => setTimeout(resolve, 5000));
            
            // 3. 检查设备状态
            const deviceService = require('./device_service.js');
            const status = await deviceService.getDeviceRealTimeStatus(deviceId);
            
            if (status) {
                console.log(`设备 ${deviceId} 基本恢复操作完成`);
            }
        } catch (error) {
            console.error(`设备 ${deviceId} 基本恢复操作失败:`, error);
        }
    }

    /**
     * 安排恢复尝试
     */
    async scheduleRecoveryAttempt(deviceId, faultType) {
        const attempts = this.recoveryAttempts.get(deviceId) || 0;
        
        if (attempts >= this.maxRecoveryAttempts) {
            console.log(`设备 ${deviceId} 恢复尝试次数已达上限 ${this.maxRecoveryAttempts}`);
            return;
        }

        this.recoveryAttempts.set(deviceId, attempts + 1);
        
        console.log(`安排设备 ${deviceId} 恢复尝试 (${attempts + 1}/${this.maxRecoveryAttempts})`);
        
        setTimeout(async () => {
            try {
                await this.attemptDeviceRecovery(deviceId, faultType);
            } catch (error) {
                console.error(`设备 ${deviceId} 恢复尝试失败:`, error);
            }
        }, this.recoveryInterval);
    }

    /**
     * 尝试设备恢复
     */
    async attemptDeviceRecovery(deviceId, faultType) {
        console.log(`尝试恢复设备 ${deviceId}, 故障类型: ${faultType}`);
        
        try {
            switch (faultType) {
                case 'offline':
                    // 尝试重新连接
                    await this.restartDeviceConnection(deviceId);
                    break;
                case 'no_response':
                    // 尝试ping设备
                    const pingResult = await this.pingDevice(deviceId);
                    if (!pingResult.success) {
                        throw new Error('设备仍无响应');
                    }
                    break;
                default:
                    // 执行基本恢复
                    await this.performBasicRecovery(deviceId);
                    break;
            }
            
            // 恢复成功，重置尝试次数
            this.recoveryAttempts.delete(deviceId);
            console.log(`设备 ${deviceId} 恢复成功`);
            
        } catch (error) {
            console.error(`设备 ${deviceId} 恢复尝试失败:`, error);
            
            // 继续安排下一次尝试
            await this.scheduleRecoveryAttempt(deviceId, faultType);
        }
    }

    /**
     * 发送离线告警
     */
    async sendOfflineAlert(deviceId, deviceStatus) {
        const alertData = {
            type: 'device_offline',
            deviceId: deviceId,
            message: `设备 ${deviceId} 已离线`,
            timestamp: Date.now(),
            deviceStatus: deviceStatus
        };
        
        await this.sendAlert(alertData);
    }

    /**
     * 发送状态异常告警
     */
    async sendStatusAbnormalAlert(deviceId, deviceStatus) {
        const alertData = {
            type: 'status_abnormal',
            deviceId: deviceId,
            message: `设备 ${deviceId} 状态异常: ${deviceStatus.switchStatus}`,
            timestamp: Date.now(),
            deviceStatus: deviceStatus
        };
        
        await this.sendAlert(alertData);
    }

    /**
     * 发送无响应告警
     */
    async sendNoResponseAlert(deviceId, deviceStatus) {
        const alertData = {
            type: 'no_response',
            deviceId: deviceId,
            message: `设备 ${deviceId} 无响应`,
            timestamp: Date.now(),
            deviceStatus: deviceStatus
        };
        
        await this.sendAlert(alertData);
    }

    /**
     * 发送未知故障告警
     */
    async sendUnknownFaultAlert(deviceId, deviceStatus) {
        const alertData = {
            type: 'unknown_fault',
            deviceId: deviceId,
            message: `设备 ${deviceId} 发生未知故障`,
            timestamp: Date.now(),
            deviceStatus: deviceStatus
        };
        
        await this.sendAlert(alertData);
    }

    /**
     * 发送告警（通用方法）
     */
    async sendAlert(alertData) {
        try {
            console.log('发送设备告警:', alertData);
            
            // 这里可以实现具体的告警发送逻辑
            // 例如：发送邮件、短信、推送通知等
            
            // 暂时只记录日志
            console.warn(`设备告警: ${alertData.message}`);
            
        } catch (error) {
            console.error('发送告警失败:', error);
        }
    }

    /**
     * 记录故障信息
     */
    recordFault(deviceId, faultRecord) {
        let deviceFaults = this.faultHistory.get(deviceId) || [];
        deviceFaults.push(faultRecord);
        
        // 只保留最近的10条故障记录
        if (deviceFaults.length > 10) {
            deviceFaults = deviceFaults.slice(-10);
        }
        
        this.faultHistory.set(deviceId, deviceFaults);
        
        console.log(`记录设备 ${deviceId} 故障:`, {
            faultType: faultRecord.faultType,
            timestamp: new Date(faultRecord.timestamp).toISOString()
        });
    }

    /**
     * 记录未知故障详细信息
     */
    async logUnknownFault(deviceId, deviceStatus) {
        const logData = {
            deviceId: deviceId,
            timestamp: Date.now(),
            deviceStatus: deviceStatus,
            message: '设备发生未知故障，需要人工检查'
        };
        
        console.error('未知设备故障:', logData);
        
        // 这里可以将详细信息写入日志文件或数据库
    }

    /**
     * 检查是否在冷却期内
     */
    isInCooldown(deviceId, currentTime) {
        const deviceFaults = this.faultHistory.get(deviceId) || [];
        if (deviceFaults.length === 0) {
            return false;
        }
        
        const lastFault = deviceFaults[deviceFaults.length - 1];
        return (currentTime - lastFault.timestamp) < this.faultCooldown;
    }

    /**
     * 获取设备故障历史
     */
    getDeviceFaultHistory(deviceId) {
        return this.faultHistory.get(deviceId) || [];
    }

    /**
     * 获取所有设备故障统计
     */
    getFaultStatistics() {
        const stats = {
            totalDevices: this.faultHistory.size,
            totalFaults: 0,
            faultTypes: {},
            recentFaults: []
        };
        
        for (const [deviceId, faults] of this.faultHistory.entries()) {
            stats.totalFaults += faults.length;
            
            for (const fault of faults) {
                // 统计故障类型
                stats.faultTypes[fault.faultType] = (stats.faultTypes[fault.faultType] || 0) + 1;
                
                // 收集最近的故障
                if (Date.now() - fault.timestamp < 24 * 60 * 60 * 1000) { // 24小时内
                    stats.recentFaults.push({
                        deviceId: deviceId,
                        faultType: fault.faultType,
                        timestamp: fault.timestamp,
                        handled: fault.handled,
                        recovered: fault.recovered
                    });
                }
            }
        }
        
        // 按时间排序最近故障
        stats.recentFaults.sort((a, b) => b.timestamp - a.timestamp);
        
        return stats;
    }

    /**
     * 清理过期的故障记录
     */
    cleanupExpiredFaults() {
        const expireTime = Date.now() - (7 * 24 * 60 * 60 * 1000); // 7天前
        
        for (const [deviceId, faults] of this.faultHistory.entries()) {
            const validFaults = faults.filter(fault => fault.timestamp > expireTime);
            
            if (validFaults.length === 0) {
                this.faultHistory.delete(deviceId);
            } else {
                this.faultHistory.set(deviceId, validFaults);
            }
        }
        
        console.log('故障记录清理完成');
    }
}

module.exports = SimpleFaultHandler;